package ProyectoX.Score;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.PriorityQueue;

public class Scorer {
	
	protected Map<String,Integer> mapeo;
	protected PriorityQueue<Entry<String,Integer>> cCP;
	protected ManipuladorArchivos mArch;
	
	public Scorer(){
		
		mArch = new ManipuladorArchivos("puntajes.txt");
		mapeo = cargarPuntajes();
		cCP = ordenarPuntajes(mapeo);
	}
	
	/**
	 * Ordena de mayor a menor los puntajes recibidos 
	 * @param toOrder Mapeo de usuario-puntaje a ordenar
	 * @return Cola con prioridad de mayor a menor
	 */
	private PriorityQueue<Entry<String, Integer>> ordenarPuntajes(Map<String,Integer> toOrder){
		PriorityQueue<Entry<String, Integer>> top5 = new PriorityQueue<Entry<String, Integer>>(5,new Comparator<Entry<String,Integer>>() {
			public int compare(Entry<String,Integer> o1, Entry<String,Integer> o2) {
				
				return o1.getValue().compareTo(o2.getValue()) * -1;
			}
		});
		for (Map.Entry<String, Integer> e : toOrder.entrySet()){
			
			top5.add(e);
		}
		
		return top5;
	}
	
	/**
	 * Carga los puntajes desde un archivo 
	 * @return Mapeo conteniendo usuario-puntaje
	 */
	//http://www.mkyong.com/java/how-to-read-file-from-java-bufferedreader-example/
	private Map<String, Integer> cargarPuntajes(){
			Map<String, Integer> puntajes = new HashMap<String,Integer>();
			String lectura = mArch.readFromFile();
			
			String sCurrentLine;
			BufferedReader bufReader = new BufferedReader(new StringReader(lectura));
			try {
				while ((sCurrentLine = bufReader.readLine()) != null) {
					
					String[] parts = sCurrentLine.split("-");
					puntajes.put(parts[0], Integer.valueOf(parts[1]));
				}
			} catch (NumberFormatException | IOException e) {e.printStackTrace();}
	 
			
			return puntajes;
		}
	
	/**
	 * Retorna el puntaje asociado a un usuario pasado por parametro, retorna null si el usuario no se encuentra
	 * @param user String
	 * @return int
	 */
	public Integer getPuntaje(String user){
		Integer puntaje = mapeo.get(user);
		return puntaje;
		
	}
	
	/**
	 * Guarda el usuario y puntaje en un archivo txt con orden de mayor a menor
	 * @param user String
	 * @param puntaje Int
	 */
	public void guardarPuntaje(String user,int puntaje){
		String output_string = "";
		mapeo.put(user,puntaje);
		cCP = ordenarPuntajes(mapeo);
		
		Entry<String,Integer> aux;
		for(int i = 0; cCP.size() > 0 || i < 5; i++){
			if (!cCP.isEmpty()){
				aux = cCP.remove();
				output_string += aux.getKey() + "-" + aux.getValue() + System.lineSeparator();	
			}
		}
		mArch.writeToFile(output_string);	
	}
	
	/**
	 * Retorna un String conteniendo los puntajes, recibe un limite de cantidad de puntajes a retornar
	 * @param limit entero, cantidad de puntajes a retornar
	 * @return
	 */
	public String toString(int limit){
		PriorityQueue<Entry<String,Integer>> aux = ordenarPuntajes(cargarPuntajes());
		Entry<String,Integer> entry_aux;
		String output_string = "";
		for(int i = 0; i < aux.size() || i < limit; i++){
			if (!aux.isEmpty()){
				entry_aux = aux.remove();
				output_string += entry_aux.getKey() + "      " + entry_aux.getValue() + System.lineSeparator();				
			}
		}
		return output_string;
	}
	

}
